using System.Reflection;
using Needle.Utils;

namespace Needle.Core.Injection {

    /// <summary>
    /// Defines a parameter and its dependency for use with an injection method.
    /// </summary>
    public interface IParameter {
        /// <summary>
        /// The dependency to inject.
        /// </summary>
        InstanceId Dependency { get;}
        /// <summary>
        /// Extra parameter info.
        /// </summary>
        ParameterInfo Info { get;}

    }
    /// <summary>
    /// Default implementation of IParameter.
    /// </summary>
    class Parameter : IParameter {

        /// <summary>
        /// An empty array of IParameters
        /// </summary>
        public static readonly IParameter[] EmptyParameters = new IParameter[0];

        /// <summary>
        /// Initializes a new Parameter instance.
        /// </summary>
        public Parameter(ParameterInfo info, string defaultDependencyName) {
            Ensure.NotNull(info, "info");

            this.m_Info = info;
            InjectAttribute attr = InjectAttribute.GetFrom(info);
            if (attr == null) {
                m_Dependency = new InstanceId(m_Info.ParameterType, defaultDependencyName);
            } else {
                m_Dependency = new InstanceId(attr.Type == null ? m_Info.ParameterType : attr.Type, attr.Name);
            }
        }
        /// <summary>
        /// Initializes a new Parameter instance.
        /// </summary>
        public Parameter(ParameterInfo info, InstanceId depId)
        {
            Ensure.NotNull(info, "info");
            Ensure.NotNull(depId, "depId");
            this.m_Info = info;
            m_Dependency = depId;
        }

        private InstanceId m_Dependency;
        /// <summary>
        /// The dependency for this parameter
        /// </summary>
        public InstanceId Dependency {
            get {
                return m_Dependency;
            }
        }

        ParameterInfo m_Info;
        /// <summary>
        /// Extra parameter information.
        /// </summary>
        public ParameterInfo Info {
            get { return m_Info; }
        }

    }
}
